package com.ww.exercise.coroutine.easy.q5

import exercise.coroutine.easy.q5.Callback
import exercise.coroutine.easy.q5.DbCallbackApi
import kotlinx.coroutines.*
import java.lang.Exception
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException

// 将Java风格的API封装为suspend函数
suspend fun DbCallbackApi.queryDb(sql: String): List<String> = suspendCancellableCoroutine { continuation ->
    // 调用Java的异步查询方法
    val thread = Thread.currentThread() // 保存当前线程引用用于取消

    query(sql, object : Callback<List<String>> {
        // 处理成功情况
        override fun onSuccess(result: List<String>) {
            // 如果协程未被取消，恢复执行并返回结果
            if (!continuation.isCancelled) {
                continuation.resume(result)
            }
        }

        // 处理失败情况
        override fun onFailure(throwable: Throwable) {
            // 如果协程未被取消，恢复执行并抛出异常
            if (!continuation.isCancelled) {
                continuation.resumeWithException(throwable)
            }
        }
    })

    // 设置协程取消处理
    continuation.invokeOnCancellation { cause ->
        // 当协程被取消时，中断数据库查询线程
        println("协程被取消：${cause?.message}")
        thread.interrupt() // 中断查询线程
    }
}

//查询成功，结果：[记录1SELECT * FROM users, 记录2SELECT * FROM users]
//查询失败：数据库查询错误：无效的SQL
//协程被取消：StandaloneCoroutine was cancelled
//查询失败或被取消：StandaloneCoroutine was cancelled
fun main() = runBlocking(Dispatchers.IO) {
    val dbApi = DbCallbackApi()

    // 测试正常查询
    try {
        val result = dbApi.queryDb("SELECT * FROM users")
        println("查询成功，结果：$result")
    } catch (e: Exception) {
        println("查询失败：${e.message}")
    }

    // 测试失败查询
    try {
        val result = dbApi.queryDb("error")
        println("查询成功，结果：$result")
    } catch (e: Exception) {
        println("查询失败：${e.message}")
    }

    // 测试协程取消
    val job = launch {
        try {
            val result = dbApi.queryDb("SELECT * FROM slow_table")
            println("查询成功，结果：${result}")
        } catch (e: Exception) {
            println("查询失败或被取消：${e.message}")
        }
    }

    // 启动后立即取消，测试取消功能
    delay(100)
    job.cancelAndJoin()
}